package io.gitee.thghh.chronicon.swing.view;

import cn.hutool.core.util.StrUtil;
import com.formdev.flatlaf.FlatClientProperties;
import com.formdev.flatlaf.FlatLaf;
import com.formdev.flatlaf.extras.FlatAnimatedLafChange;
import com.formdev.flatlaf.extras.FlatSVGIcon;
import com.formdev.flatlaf.util.LoggingFacade;
import com.jidesoft.dialog.JideOptionPane;
import com.jidesoft.swing.JideTabbedPane;
import io.gitee.thghh.chronicon.swing.components.AdjustableStyle;
import io.gitee.thghh.chronicon.swing.components.AdjustableUI;
import io.gitee.thghh.chronicon.swing.components.MainTabbedPaneUI;
import io.gitee.thghh.chronicon.swing.components.ReflectionRepaintManager;
import io.gitee.thghh.chronicon.swing.theme.DarkTheme;
import io.gitee.thghh.chronicon.swing.theme.GlazzedTheme;
import io.gitee.thghh.chronicon.swing.theme.LightTheme;
import io.gitee.thghh.chronicon.swing.utils.IconLoader;
import org.springframework.stereotype.Component;

import javax.swing.*;
import javax.swing.event.ChangeEvent;
import javax.swing.event.ChangeListener;
import java.awt.*;
import java.awt.event.*;
import java.awt.image.BufferedImage;
import java.time.LocalDateTime;
import java.time.format.DateTimeFormatter;

/**
 * 主页面框架
 *
 * @author pengzhikang
 * @date 2025/3/19 17:21
 * @since 1.0.0
 */
public class MainFrame extends JFrame implements AdjustableUI, AdjustableStyle {

    private static MainFrame instance;
    private static final String PREFS_ROOT_PATH = "/chronicon-swing";
    private static final DateTimeFormatter TIME_FORMATTER = DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm");
    private BufferedImage backgroundImageDark;
    private BufferedImage backgroundImageLight;

    private SidePane sidePane;
    private JButton refreshBut;

    private JPanel content;
    private JToolBar statusBar;
    private JideTabbedPane tabbedPane;
    private JToggleButton menuBut;
    private JToolBar tabLeadingBar;
    private JToolBar tabTrailingBar;

    private TitleMenuBar titleMenuBar;


    public MainFrame() {
        MainPrefs.init(PREFS_ROOT_PATH);
        setUndecorated(true);

        setDefaultCloseOperation(JFrame.DISPOSE_ON_CLOSE);

        addWindowListener(new WindowAdapter() {
            @Override
            public void windowClosed(WindowEvent e) {
                System.exit(0);
            }
        });

        installRepaintManager();
    }


    private void installRepaintManager() {
        ReflectionRepaintManager manager = new ReflectionRepaintManager();
        RepaintManager.setCurrentManager(manager);
    }

    public static MainFrame getInstance() {
        if (instance == null) {
            instance = new MainFrame();
        }
        return instance;
    }


    @Override
    public void setBackground(Color bgColor) {
        super.setBackground(bgColor);
    }


    @Override
    public void adjustUI() {
        this.showMenuBar(true);
        rootPane.putClientProperty(FlatClientProperties.FULL_WINDOW_CONTENT, false);

        this.setBackground(null);
        rootPane.setBorder(BorderFactory.createEmptyBorder(0, 0, 0, 0));
        rootPane.setWindowDecorationStyle(JRootPane.FRAME);

        content = new JPanel(new BorderLayout()) {
            @Override
            protected void paintComponent(Graphics g) {
                Graphics2D g2 = (Graphics2D) g.create();
                if (StrUtil.equals(UIManager.getLookAndFeel().getName(), DarkTheme.NAME)) {
                    g2.setColor(UIManager.getColor("App.mainPaneBackground"));
                    g2.fillRect(0, 0, getWidth(), getHeight());
                } else if (StrUtil.equals(UIManager.getLookAndFeel().getName(), LightTheme.NAME)) {
                    g2.drawImage(getBackgroundImageLight(), 0, 0, getWidth(), getHeight(), this);
                } else if (StrUtil.equals(UIManager.getLookAndFeel().getName(), GlazzedTheme.NAME)) {
                    g2.drawImage(getBackgroundImageDark(), 0, 0, getWidth(), getHeight(), this);
                }
                g2.dispose();
            }
        };

        content.add(getSidePane(), BorderLayout.WEST);
        content.add(getStatusBar(), BorderLayout.SOUTH);
        content.add(getTabbedPane(), BorderLayout.CENTER);
        this.setContentPane(content);

        this.setSize(960, 650);
        this.setResizable(true);
        this.setLocationRelativeTo(null);
        this.setVisible(true);
        this.setExtendedState(JFrame.MAXIMIZED_BOTH);

    }


    public JToolBar getTabLeadingBar() {
        if (tabLeadingBar == null) {
            tabLeadingBar = new JToolBar() {
                @Override
                public Dimension getPreferredSize() {
                    return new Dimension(super.getPreferredSize().width, 60);
                }
            };
            tabLeadingBar.setOpaque(false);
            tabLeadingBar.add(menuBut = new JToggleButton(new FlatSVGIcon("icons/bars.svg", 25, 25)));
            tabLeadingBar.add(refreshBut = new JButton(new FlatSVGIcon("icons/refresh.svg", 25, 25)));
            menuBut.setSelected(true);
            menuBut.addItemListener(new ItemListener() {
                @Override
                public void itemStateChanged(ItemEvent e) {
                    sidePane.setVisible(menuBut.isSelected());
                }
            });
        }
        return tabLeadingBar;
    }

    public JToolBar getTabTrailingBar() {
        if (tabTrailingBar == null) {
            tabTrailingBar = new JToolBar() {
                @Override
                public Dimension getPreferredSize() {
                    return new Dimension(super.getPreferredSize().width, 60);
                }
            };
        }
        return tabTrailingBar;
    }

    public BufferedImage getBackgroundImageDark() {
        if (backgroundImageDark == null) {
            backgroundImageDark = IconLoader.image("/images/bg2.jpg");
        }
        return backgroundImageDark;
    }

    public BufferedImage getBackgroundImageLight() {
        if (backgroundImageLight == null) {
            backgroundImageLight = IconLoader.image("/images/mainBack.png");
        }
        return backgroundImageLight;
    }

    public JideTabbedPane getTabbedPane() {
        if (tabbedPane == null) {
            tabbedPane = new JideTabbedPane();
            tabbedPane.setShowCloseButton(true);
            tabbedPane.setShowCloseButtonOnTab(true);
            tabbedPane.setShowCloseButtonOnMouseOver(true);
            tabbedPane.addTab("主页", new FlatSVGIcon("icons/home.svg", 25, 25), new JLabel());
            tabbedPane.setTabClosableAt(0, false);
            tabbedPane.setTabLeadingComponent(getTabLeadingBar());
            tabbedPane.setTabTrailingComponent(getTabTrailingBar());
            tabbedPane.addChangeListener(new ChangeListener() {
                @Override
                public void stateChanged(ChangeEvent e) {
                    tabForegroundChanged();
                }
            });
//            tabbedPane.setBoldActiveTab(true);

            tabbedPane.setUI(new MainTabbedPaneUI());
            tabbedPane.setFont(UIManager.getFont("Label.font").deriveFont(16f));
            tabForegroundChanged();

            tabbedPane.addMouseListener(new MouseAdapter() {
                @Override
                public void mouseReleased(MouseEvent e) {
                    super.mouseReleased(e);
                    if (SwingUtilities.isRightMouseButton(e)) {
                        showPopupMenu(e);
                    }
                }
            });

        }
        return tabbedPane;
    }

    public void addTab() {
        tabForegroundChanged();
    }


    private void tabForegroundChanged() {
        int tabCount = tabbedPane.getTabCount();
        int selectCount = tabbedPane.getSelectedIndex();
        for (int i = 0; i < tabCount; i++) {
            FlatSVGIcon icon = (FlatSVGIcon) tabbedPane.getIconAt(i);
            if (icon == null) {
                continue;
            }
            Color color = null;

            if (selectCount == i) {
                color = UIManager.getColor("TabbedPane.selectedForeground");

            } else {
                color = UIManager.getColor("Label.foreground");
            }
            tabbedPane.setForegroundAt(i, color);
            tabbedPane.setBackground(UIManager.getColor("TabbedPane.background"));
            Color finalColor = color;
            icon.setColorFilter(new FlatSVGIcon.ColorFilter(c -> finalColor));

        }
    }

    public JMenuBar getTitleMenuBar() {
        if (titleMenuBar == null) {
            titleMenuBar = new TitleMenuBar(this);
        }
        return titleMenuBar;
    }

    public SidePane getSidePane() {
        if (sidePane == null) {
            sidePane = new SidePane();
            sidePane.setBorder(BorderFactory.createMatteBorder(0, 0, 0, 1, UIManager.getColor("App.borderColor")));
        }
        return sidePane;
    }

    public JToolBar getStatusBar() {
        if (statusBar == null) {
            statusBar = new JToolBar();
            statusBar.setFloatable(false);
            statusBar.setPreferredSize(new Dimension(0, 45));
            statusBar.setBorder(BorderFactory.createMatteBorder(1, 0, 0, 0, UIManager.getColor("App.borderColor")));

            statusBar.add(Box.createGlue());
            JLabel label = new JLabel("代码生成");
            statusBar.add(label);
            statusBar.add(Box.createGlue());
            // 时间标签
            JLabel timeLabel = new JLabel(TIME_FORMATTER.format(LocalDateTime.now()), SwingConstants.CENTER);
//            timeLabel.setFont(timeLabel.getFont().deriveFont(18f));
            Timer timer = new Timer(1000, event -> timeLabel.setText(TIME_FORMATTER.format(LocalDateTime.now())));
            timer.start();
            statusBar.add(timeLabel);
            statusBar.add(Box.createHorizontalStrut(15));


        }
        return statusBar;
    }


    private void showMenuBar(boolean isShow) {
        setJMenuBar(isShow ? getTitleMenuBar() : null);
        this.revalidate();
        this.repaint();
    }


    @Override
    public void dispose() {
        super.dispose();
    }

    @Override
    public void setTitle(String title) {
        super.setTitle(title);
//        getTitleLabel().setText(title);
    }


    private void showPopupMenu(final MouseEvent event) {

        // 如果当前事件与右键菜单有关（单击右键），则弹出菜单
        final int index = ((JTabbedPane) event.getComponent()).getUI().tabForCoordinate(tabbedPane, event.getX(), event.getY());
        final int count = ((JTabbedPane) event.getComponent()).getTabCount();
        final String title = tabbedPane.getTitleAt(index);

        if (index == -1) {
            return;
        }
        JPopupMenu pop = new JPopupMenu();
        JMenuItem closeCurrent = new JMenuItem("关闭当前");
        closeCurrent.setPreferredSize(new Dimension(140, 30));

        closeCurrent.addMouseListener(new MouseAdapter() {
            @Override
            public void mouseReleased(MouseEvent e) {
                if (tabbedPane.isTabClosableAt(index)) {
                    tabbedPane.removeTabAt(index);
                }
            }
        });
        pop.add(closeCurrent);
        pop.addSeparator();

        JMenuItem closeLeft = new JMenuItem("关闭左侧标签");
        closeLeft.setPreferredSize(new Dimension(140, 30));

        closeLeft.addMouseListener(new MouseAdapter() {
            @Override
            public void mouseReleased(MouseEvent e) {
                for (int j = (index - 1); j >= 0; j--) {
                    if (tabbedPane.isTabClosableAt(j)) {
                        tabbedPane.removeTabAt(j);
                    }
                }
            }
        });
        pop.add(closeLeft);

        JMenuItem closeRight = new JMenuItem("关闭右侧标签");
        closeRight.setPreferredSize(new Dimension(140, 30));

        closeRight.addMouseListener(new MouseAdapter() {
            @Override
            public void mouseReleased(MouseEvent e) {
                for (int j = (count - 1); j > index; j--) {
                    if (tabbedPane.isTabClosableAt(j)) {
                        tabbedPane.removeTabAt(j);
                    }
                }
            }
        });
        closeRight.setPreferredSize(new Dimension(140, 30));
        pop.add(closeRight);

        JMenuItem other = new JMenuItem("关闭其它标签");
        other.setPreferredSize(new Dimension(140, 30));

        other.addMouseListener(new MouseAdapter() {
            @Override
            public void mouseReleased(MouseEvent e) {
                int tabCount = count;
                while (tabCount-- > 0) {
                    if (title.equals(tabbedPane.getTitleAt(tabCount))) {
                        continue;
                    }
                    if (tabbedPane.isTabClosableAt(tabCount)) {
                        tabbedPane.removeTabAt(tabCount);
                    }
                }
            }
        });
        pop.add(other);
        pop.addSeparator();

        JMenuItem all = new JMenuItem("关闭所有标签");
        all.setPreferredSize(new Dimension(140, 30));

        all.addMouseListener(new MouseAdapter() {
            @Override
            public void mouseReleased(MouseEvent e) {
                int tabCount = count;
                // We invoke removeTabAt for each tab, otherwise we may end up
                // removing Components added by the UI.
                while (tabCount-- > 0) {

                    if (tabbedPane.isTabClosableAt(tabCount)) {
                        tabbedPane.removeTabAt(tabCount);
                    }
                }
            }
        });
        pop.add(all);

        pop.show(event.getComponent(), event.getX(), event.getY());

    }

    @Override
    public void adjustStyle() {
        rootPane.putClientProperty(FlatClientProperties.TITLE_BAR_SHOW_TITLE, false);
        rootPane.putClientProperty(FlatClientProperties.TITLE_BAR_BACKGROUND, UIManager.getColor("App.titleBarBackground"));
        rootPane.putClientProperty(FlatClientProperties.TITLE_BAR_FOREGROUND, UIManager.getColor("App.titleBarForeground"));

        sidePane.setBorder(BorderFactory.createMatteBorder(0, 0, 0, 1, UIManager.getColor("App.borderColor")));
        statusBar.setBorder(BorderFactory.createMatteBorder(1, 0, 0, 0, UIManager.getColor("App.borderColor")));

        content.setBorder(BorderFactory.createMatteBorder(1, 0, 0, 0, UIManager.getColor("App.borderColor")));
        tabForegroundChanged();
    }
}